#!/usr/bin/env python
#
#   urldb.py - URL database
#   
#
from string import upper

class UrlDB():
    '''
    Database for URLs
    
    ROW:
        url = string
        type = string: '', 'EDGE', 'CHECK_ONCE'
        md5 = string
        status = string: '', 'DONE'
        content = text
    '''
    def __init__(self):
        ''' 
        init 
        '''
        self.__db = {}

    def add(self, url, **kwargs):
        '''
        Add URL to database
        '''
        if url not in self.__db.keys():
            self.__db[url] = kwargs

    def delete(self, url=None, urls=[]):
        '''
        delete url or urls
        '''
        if url: del(self.__db[url])
        elif len(urls) > 0:
            for u in urls: del(self.__db[u])

    def update(self, url, **kwargs):
        '''
        update URL info
        '''
        for i in kwargs.keys():
            if i in ("type", "md5", "status",):
                self.__db[url][i] = kwargs[i]
            else:
                print "Error! Unknown parameter: %s" % i

    def filter(self, **kwargs):
        '''
        filter urls
        
        '''
        urls = set()
        for c in kwargs.keys():
            if c in ("type", "md5", "status",):
                urls_c = []
                for url in self.__db.keys():
                    if upper(self.__db[url][c]) == upper(kwargs[c]): urls_c.append(url)
                if len(urls) == 0: 
                    urls = set(urls_c)
                else:
                    urls = urls & set(urls_c)
        return list(urls)
                

    def load_from_json(self, filename):
        '''
        load urls_db from json file
        '''
        import json
        try:
            self.__db = json.load(open(filename, 'rb'))
        except IOError:
            return False
        return True

    def save_to_json(self, filename):
        '''
        save urls_db in json file
        '''
        import json
        try:
            json.dump(self.__db, open(filename, 'wb'))
        except IOError:
            return False
        return True

    def stat(self):
        '''
        simple statistics
        
        return: handled / total urls
        '''
        not_checked = len([u['status'] for u in self.__db.values() if u['status'] == ''])
        edge = len([u['type'] for u in self.__db.values() if upper(u['type']) == 'EDGE'])
        total = len(self.__db.values())
        return {'not_checked': not_checked, "edge": edge, "total": total}

    def as_table(self, urls=[]):
        '''
        return url db as table
        '''
        table = []
        
        if len(urls) == 0: urls = self.__db.keys()
                    
        for url in urls:
            table.append( {
                            "url": url, \
                            "type": self.__db[url]['type'], \
                            "status": self.__db[url]['status'], \
                            "md5": self.__db[url]['md5'], \
            } )
        return table

if __name__ == "__main__":

    from optparse import OptionParser
    import sys
	
    parser = OptionParser()
    parser.add_option("-i", "--input", dest="input", help="json input file")
    parser.add_option("-v", "--view", dest="view", help="view format: table")
    parser.add_option("-f", "--filter", dest="filter", help="url filter, define as 'var1=val1&var2=val2'")
    parser.add_option("-s", "--set", dest="set", help="set values for paramaters, define as 'var1=val1&var2=val2'")
    parser.add_option("-d", "--delete", dest="delete", action='store_true', help="delete filtered urls")
    (options, args) = parser.parse_args()

    if options.input == None:
        parser.error("Incorrect number of arguments, \n\nuse -h or --help for detail\n")
        sys.exit()

    urls_db = UrlDB()
    urls_db.load_from_json(options.input)

    urls = []
    if options.filter:
        params = {}
        for c in options.filter.split('&'):
            p_name = c.split('=')[0]
            p_value = c.split('=')[1]
            if p_name in ("type", "md5", "status"):
                params[p_name] = p_value
        urls = urls_db.filter(**params)
        
    if options.delete:
        print "Delete urls"
        urls_db.delete(urls=urls)
        urls_db.save_to_json(options.input)
        sys.exit()

    if options.set:
        params = {}
        for c in options.set.split('&'):
            p_name = c.split('=')[0]
            p_value = c.split('=')[1]
            if p_name in ("type", "md5", "status"):
                params[p_name] = p_value
        for u in urls: 
            urls_db.update(u, **params)
        urls_db.save_to_json(options.input)

    if options.view == 'table':
        if len(urls) == 0 and options.filter:
            print "Not found" 
        else:
            for row in urls_db.as_table(urls):
                print row
    else:
        parser.error("Incorrect number of arguments, \n\nuse -h or --help for detail\n")
        sys.exit()
    
    
    
